package cn.melonlib.apis.support.comp.service;

import cn.hutool.core.io.file.FileWriter;
import cn.melonlib.apis.http.comp.action.ApiRequestAction;
import cn.melonlib.apis.http.comp.action.ApiResponseBody;
import cn.melonlib.apis.support.model.entity.ApiRequestRecord;
import cn.melonlib.apis.support.model.enums.ApiOperationType;
import cn.melonlib.apis.support.model.view.ApiRequestRecordView;
import cn.melonlib.cores.commons.comp.service.impl.WorkerBasicService;
import cn.melonlib.cores.commons.comp.utils.DateTimeUtils;
import cn.melonlib.cores.model.anno.WorkerParameter;
import lombok.Getter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.intellij.lang.annotations.Language;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.core.token.TokenService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Service
@Getter
public class ApiRequestRecordService extends WorkerBasicService<ApiRequestRecord> {

//    @Value("${system.logs.apis.file.path:/service/logs/api}")
//    private String fileStorePath;

    @Value("${system.logs.apis.expires:3d}")
    private String expires;

//    @Value("${system.logs.apis.file.open:true}")
//    private boolean fileStore;

    @Resource
    private DateTimeUtils dateTimeUtils;

    @Resource
    private ApiRequestAction apiRequestAction;

    private LinkedList<ApiRequestRecord> cached=new LinkedList<>();


    @Transactional(value = Transactional.TxType.REQUIRES_NEW,rollbackOn = Exception.class)
    public ApiRequestRecord sendRequest(
            @WorkerParameter(value = "apiUrl",comment = "请求链接",required = true) String apiUrl,
            @WorkerParameter(value = "statement",comment = "执行语句",required = true) String statement,
            @WorkerParameter(value = "variables",comment = "请求参数",required = true) Map<String,Object> variables,
            @WorkerParameter(value = "apiOperationType",comment = "操作类型",required = true) String apiOperationType,
            @WorkerParameter(value = "apiRange",comment = "操作范围",required = true) String apiRange,
            @WorkerParameter(value = "tenantId",comment = "所属租户",required = true) String tenantId,
            @WorkerParameter(value = "operationName",comment = "操作名称") String operationName,
            @WorkerParameter(value = "headers",comment = "请求头")Map<String,String> headers
            ) throws Exception{
        ApiRequestRecord apiRequestRecord=new ApiRequestRecord();
        apiRequestRecord.setApiRange(apiRange);
        apiRequestRecord.setApiUrl(apiUrl);
        apiRequestRecord.setOperationName(operationName);
        apiRequestRecord.setStatement(statement);
        apiRequestRecord.setVariables(getJsonMapper().writeValueAsString(variables));
        apiRequestRecord.setOperationType(ApiOperationType.valueOf(apiOperationType));
        apiRequestRecord.setTenantId(tenantId);
        apiRequestRecord.setTenantCode(tenantId);
//        headers.put("X-Correlation-ID","");
//        long start=System.currentTimeMillis();
        logger.debug("api_url:"+apiUrl);
        logger.debug("statement:"+statement);
        logger.debug("params:"+variables);
        ApiResponseBody responseBody=apiRequestAction.post(apiUrl,variables,headers,"application/json;charset=UTF-8");
        apiRequestRecord.setResponse(responseBody.body());
        apiRequestRecord.setResponseCode(responseBody.code());
        apiRequestRecord.setUseTime(responseBody.endTime()-responseBody.startTime());
        apiRequestRecord.setResponseDateTime(responseBody.endTime());
        apiRequestRecord.setRequestHeader(getJsonMapper().writeValueAsString(headers));
        synchronized (cached) {
            cached.push(apiRequestRecord);
            cached.notify();
        }
//        long time=dateTimeUtils.expiresValue(expires);
//        if(time<0){
//            return dao.save(apiRequestRecord).getResult();
//        }
//        if(time==0){
//            if(fileStore) {
//                String path = fileStorePath + "/" + DateFormatUtils.format(System.currentTimeMillis(), "yyyy/MM/dd") + "/api.log";
//                FileUtils.forceMkdirParent(new File(path));
//                File file = new File(path);
//                if (!file.exists()) {
//                    FileUtils.touch(file);
//                }
//                FileWriter.create(new File(path), StandardCharsets.UTF_8).appendLines(List.of(getJsonMapper().writeValueAsString(apiRequestRecord)));
//            }
//            return apiRequestRecord;
//        }
//        ApiRequestRecord recordSave= dao.save(apiRequestRecord).getResult();
//        if(fileStore) {
//            String path = fileStorePath + "/" + DateFormatUtils.format(System.currentTimeMillis(), "yyyy/MM/dd") + "/api.log";
//            FileUtils.forceMkdirParent(new File(path));
//            File file = new File(path);
//            if (!file.exists()) {
//                FileUtils.touch(file);
//            }
//            FileWriter.create(new File(path), StandardCharsets.UTF_8).appendLines(List.of(getJsonMapper().writeValueAsString(recordSave)));
//        }

        return apiRequestRecord;
    }



    @Transactional(value = Transactional.TxType.REQUIRES_NEW,rollbackOn = Exception.class)
    public void saveLogs() throws Exception{
        long time = dateTimeUtils.expiresValue(expires);
        if (time != 0) {
            logger.info("保存api日志信息>>>" + cached.size() + "条");
            cached.forEach(e->{
                dao.save(e);
            });
            @Language("HQL") String query = "delete from ApiRequestRecord where createDateTime < ?1";
            if (time > 0) {
                int num = dao.updateQl(query, List.of(time));
                logger.info("清理api日志信息>>>" + num + "条");
            }
        }
        cached.clear();

    }

    public ApiRequestRecordView detail(String id){
        return new ApiRequestRecordView(dao.getEntity(ApiRequestRecord.class,id),getJsonMapper());
    }
}
